package com.llllz.letscdf.views; import android.content.Context; import android.graphics.drawable.Drawable; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Handler; import android.os.Looper; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.FrameLayout; import com.llllz.letscdf.R; import com.llllz.letscdf.listener.CardListener; import com.llllz.letscdf.listener.SecondCardBgListener; import com.llllz.letscdf.model.Recommend; import com.llllz.letscdf.model.Sex; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.Animator.AnimatorListener; import com.nineoldandroids.animation.AnimatorSet; import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.view.ViewHelper; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import legency.graphic.drawable.TransitionDrawable; public class CardFrameLayout extends FrameLayout implements CardListener, SecondCardBgListener { static List<Recommend> recommends = new ArrayList<Recommend>(); private Handler handler_ = new Handler(Looper.getMainLooper()); static { recommends .add(new Recommend( "http://img.hb.aicdn.com/1c3aa587b19bcf10265a94a3652f44211da473a9117c1-5gsfIa_fw658", "梁冰洁", 23, Sex.FeMale)); recommends .add(new Recommend( "http://h.hiphotos.baidu.com/image/w%3D2048/sign=ee5d17e0cd11728b302d8b22fcc4c2ce/d833c895d143ad4bee4edeb182025aafa40f065a.jpg", "林峰", 25, Sex.Male)); recommends .add(new Recommend( "http://h.hiphotos.baidu.com/image/w%3D2048/sign=4ee924006509c93d07f209f7ab05f9dc/d50735fae6cd7b8919af548d0d2442a7d8330ef8.jpg", "付辛博", 25, Sex.Male)); recommends .add(new Recommend( "http://img.hb.aicdn.com/c62687ef14a35418efcd2ae1612aa3f43afb6cf822319-xONtrI_fw658", "王媛媛", 25, Sex.FeMale)); recommends .add(new Recommend( "http://d.hiphotos.baidu.com/image/w%3D2048/sign=bb286929347adab43dd01c43bfecb21c/503d269759ee3d6d16ca5dca41166d224f4adea7.jpg", "钟汉良", 25, Sex.Male)); recommends .add(new Recommend( "http://img.hb.aicdn.com/917cfd578c5a9162e3f7ce86f7c01436e7c449c110da6-5mVW63_fw658", "杜小娟", 22, Sex.FeMale)); recommends .add(new Recommend( "http://img.hb.aicdn.com/62ee472a1246194453b1305a5ffa01fe4a684fa711754-9JWyy1_fw658", "琳可爱", 26, Sex.FeMale)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=1ec5b79cc9ef76093c0b9e9f1ae5a2cc/2cf5e0fe9925bc314e51b2995cdf8db1cb1370a6.jpg", "李敏镐", 30, Sex.Male)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=cb1da37d4dc2d562f208d7edd32990ef/cdbf6c81800a19d8ce1b891831fa828ba61e4696.jpg", "吴彦祖", 25, Sex.Male)); recommends .add(new Recommend( "http://img.hb.aicdn.com/e3eb4d45511cdadf119b544ebfe18c1b00f5da9213e95-swfS2y_fw658", "刘璐", 26, Sex.FeMale)); recommends .add(new Recommend( "http://img.hb.aicdn.com/63119509d36ca51394777b02c78b69a9573136751a30f-on8cFK_fw658", "方爱华", 26, Sex.FeMale)); recommends .add(new Recommend( "http://img.hb.aicdn.com/5106a594badfd08e14aa369d5004fff37feea84cb52d8-6ROKtN_fw658", "江心可", 33, Sex.FeMale)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=1e0a7c2135a85edffa8cf9237d6c0823/3ac79f3df8dcd100189aed50738b4710b9122fb8.jpg", "黄晓明", 25, Sex.Male)); recommends .add(new Recommend( "http://img.hb.aicdn.com/6d09a260af6e61ec4ebbe6ef6ad984f1e0272f2c229af-JvZW0q_fw658", "Linda", 18, Sex.FeMale)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=09400ab58e5494ee8722081919cde1fe/241f95cad1c8a7863389c1046509c93d70cf501d.jpg", "路秋水", 26, Sex.FeMale)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=1ec5b79cc9ef76093c0b9e9f1ae5a2cc/2cf5e0fe9925bc314e51b2995cdf8db1cb1370a6.jpg", "李敏镐", 30, Sex.Male)); /*recommends .add(new Recommend( "http://d.hiphotos.baidu.com/image/w%3D2048/sign=c4734d1540a7d933bfa8e3739973d013/8718367adab44aede5b3c9e5b11c8701a18bfb36.jpg", "张欣", 25, Sex.FeMale)); recommends .add(new Recommend( "http://g.hiphotos.baidu.com/image/w%3D2048/sign=5709fdc080025aafd33279cbcfd5ab64/8601a18b87d6277f183589382a381f30e924fc8f.jpg", "王小琴", 26, Sex.FeMale));*/ recommends .add(new Recommend( "http://img.hb.aicdn.com/63119509d36ca51394777b02c78b69a9573136751a30f-on8cFK_fw658", "方爱华", 26, Sex.FeMale)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=1c1b01c39252982205333ec3e3f27acb/11385343fbf2b211c92bb84ac88065380cd78ea8.jpg", "林冰凉", 33, Sex.FeMale)); recommends .add(new Recommend( "http://c.hiphotos.baidu.com/image/w%3D2048/sign=1e0a7c2135a85edffa8cf9237d6c0823/3ac79f3df8dcd100189aed50738b4710b9122fb8.jpg", "黄晓明", 25, Sex.Male)); recommends .add(new Recommend( "http://ent.iyaxin.com/attachement/jpg/site2/20110805/0019667873730fa5f68753.jpg", "章子怡", 25, Sex.FeMale)); /*recommends .add(new Recommend( "http://a.hiphotos.baidu.com/image/w%3D2048/sign=a5906bede51190ef01fb95dffa239c16/bd3eb13533fa828b86bb26e3ff1f4134970a5a11.jpg", "赵林芳", 18, Sex.FeMale));*/ } LinkedList<Card> cards = new LinkedList<Card>(); /** * �����ں���IJ���ʾ����Ч���ĸ��� */ public static final int noanimationmax = 1; private static final int cardscount = 5; private int noanimationsize; static CardState offset = new CardState(); static { offset.mScaleX = -0.02f; offset.mScaleY = -0.02f; // offset.my=5; offset.mTranslationY = 25; } private Context mContext; private Animation mAnimFadeIn; private Card mCurrent; private SensorManager mSensorManager; private Sensor mAccelerometer; private CardState state; private AnimatorSet animatorSet; private boolean processing; private Thread addcard; private Drawable currentbg; private Drawable secbg; public CardFrameLayout(Context context) { super(context); init(context); } public CardFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CardFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { Log.i("init", "init"); mContext = context; initSensor(context); this.setLayerType(View.LAYER_TYPE_HARDWARE, null); mAnimFadeIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_quick_fade_in); addcard = new Thread(new CardAdd()); addcard.start(); } class CardAdd implements Runnable { @Override public void run() { while (true) { Recommend card = getCard(); if (card != null) { // TODO add lock if (cards.size() < cardscount) addCard(card); } else { } } } } Recommend getCard() { if (recommends != null && recommends.size() > 0) return recommends.get(0); else return null; } public void addCard(Recommend recommend) { // Log.i("new Card added", recommend.toString()); Card card = new Card(mContext); card.setGravity(Gravity.CENTER); cards.addLast(card); int index = cards.indexOf(card); if (index == 0) { mCurrent = card; cardStateChanged(); } if (index == 1) { card.setBgChangeListener(this); } card.bind(recommend); AnimatorSet animatorSet = new AnimatorSet(); Collection<Animator> items = new ArrayList<Animator>(); if (state == null) { state = card.reserveCardState(); items.addAll(state.getAnimation(card)); } else { Collection<? extends Animator> a = getCarStateofIndex(index) .getAnimation(card); items.addAll(a); } animatorSet.playTogether(items); runAnimation(animatorSet, card); recommends.remove(recommend); } private void cardStateChanged() { mCurrent.setChoiceListener(this); } void runAnimation(final AnimatorSet animatorSet, final Card card) { handler_.post(new Runnable() { @Override public void run() { addView(card, 0); animatorSet.setDuration(300L).start(); } }); } Collection<Animator> animationTonew() { Collection<Animator> items = new ArrayList<Animator>(); for (Card card : cards) { int index = cards.indexOf(card); Collection<? extends Animator> a = getCarStateofIndex(index) .getAnimation(card); items.addAll(a); } return items; } CardState getCarStateofIndex(int index) { CardState s = state.clone(); int divindex = cardscount - noanimationsize - 1; float rate; if (index <= divindex) { rate = getrate(index, cardscount); } else { rate = getrate(divindex, cardscount); } s.addoffset(offset, rate); return s; } boolean isAnimationStarted() { return animatorSet != null && animatorSet.isStarted(); } void initSensor(Context context) { mSensorManager = (SensorManager) context .getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager .getDefaultSensor(Sensor.TYPE_ACCELEROMETER); SensorEventListener a = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) return; // low-pass filter to make the movement more stable if (mCurrent != null && !mCurrent.isTouching() && !mCurrent.isAnimating() && !isAnimationStarted()) { mCurrent.sensorEventChange(event); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }; // mSensorManager.registerListener(a, mAccelerometer, // SensorManager.SENSOR_DELAY_UI); } private float getrate(int i, int showsize) { if (i == 0) return 0; return (1 - i / showsize) * (i + 1); } void removeFirst() { Card a = cards.poll(); if (a != null) { removeView(a); } animationTonew(); } public AnimatorListener getCardRemovedListener(final Card p) { return new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { removeView(p); mCurrent = cards.peek(); if (mCurrent != null) { mCurrent.reserveCardState(); cardStateChanged(); if (cards.size() > 1 && cards.get(1) != null) { cards.get(1).setBgChangeListener(CardFrameLayout.this); } } processing = false; } @Override public void onAnimationCancel(Animator animation) { } }; } public Animation.AnimationListener getStampAnimationListener( final AnimatorSet animatorset) { return new Animation.AnimationListener() { public void onAnimationEnd(Animation paramAnimation) { animatorset.start(); getBg().startTransition(300L); } public void onAnimationRepeat(Animation paramAnimation) { } public void onAnimationStart(Animation paramAnimation) { } }; } @Override public void likeswiped() { like(false); } public void like(boolean withStamp) { animateOut(true, withStamp); } void animateOut(boolean like, boolean withStamp) { if (processing) return; processing = true; Card current = cards.poll();// should not release lock if (current != null) { animatorSet = new AnimatorSet(); Collection<Animator> animatorsa = animationTonew(); int i = 800 * (like ? 1 : -1); ObjectAnimator toright = ObjectAnimator.ofFloat(current, "translationX", i); animatorsa.add(toright); animatorSet.addListener(getCardRemovedListener(current)); animatorSet.setDuration(300L).playTogether(animatorsa); if (withStamp) { View stamp = (like ? mCurrent.getLike() : mCurrent.getHate()); stamp.setVisibility(View.VISIBLE); ViewHelper.setAlpha(stamp, 0.8f); mAnimFadeIn .setAnimationListener(getStampAnimationListener(animatorSet)); stamp.startAnimation(mAnimFadeIn); } else { animatorSet.start(); } // TODO release lock } } public void hated(boolean withStamp) { animateOut(false, withStamp); } @Override public void hateswiped() { hated(false); } public void show() { } @Override public void onmove(float x) { float rate = Math.min(Math.abs(x) / 220.0F, 1.0F); for (int i = 1; i < cards.size() - noanimationsize; i++) { Card animationcard = cards.get(i); if (animationcard == null) break; animateFormTo(animationcard, i, i - 1, rate); } if (getBackground() != null && getBackground() instanceof TransitionDrawable) ((TransitionDrawable) getBackground()).setRate(rate); } private void animateFormTo(View view, int orgindex, int target, float rate) { CardState.animateFormTo(view, getCarStateofIndex(orgindex), getCarStateofIndex(target), rate); } @Override public void resetPosition() { animatorSet = new AnimatorSet(); Collection<Animator> items = new ArrayList<Animator>(); for (int i = 1; i < cards.size() - noanimationsize; i++) { Card animationcard = cards.get(i); if (animationcard == null) break; items.addAll(getCarStateofIndex(i).getAnimation(animationcard)); } animatorSet.playTogether(items); animatorSet.setDuration(300L).start(); if (getBg() != null) getBg().reverse(300L); } @Override public void ImageLoaded(Drawable drawable) { currentbg = drawable; buindTrD(); } TransitionDrawable buindTrD() { boolean anim = false; if (currentbg == null) return null; Drawable[] layers = new Drawable[2]; if (secbg != null) { layers[0] = currentbg; layers[1] = secbg; } else { layers[0] = getResources().getDrawable(R.drawable.wall_bg); layers[1] = currentbg; anim = true; } TransitionDrawable t = new TransitionDrawable(layers); setBackground(t); t.setCrossFadeEnabled(true); if (anim) t.startTransition(1500); return t; } @Override public void secbgloaded(Drawable drawable) { secbg = drawable; buindTrD(); } TransitionDrawable getBg() { return ((TransitionDrawable) getBackground()); } }